<template>
	<div>
		<el-card class="box-card">
			<div slot="header" class="clearfix">
				<span>文章列表</span>
			</div>
			<!-- 搜索区域 -->
			<div class="search-box">
				<el-form :inline="true" :model="q">
					<el-form-item label="文章分类">
						<el-select v-model="q.cate_id" placeholder="请选择分类" size="small">
							<!-- 循环渲染可选项 -->
							<el-option v-for="item in cateList" :key="item.id" :label="item.cate_name" :value="item.id">
							</el-option>
						</el-select>
					</el-form-item>
					<el-form-item label="发布状态" style="margin-left: 15px;">
						<el-select v-model="q.state" placeholder="请选择状态" size="small">
							<el-option label="已发布" value="已发布"></el-option>
							<el-option label="草稿" value="草稿"></el-option>
						</el-select>
					</el-form-item>
					<el-form-item>
						<el-button type="primary" size="small" @click="initArtList">筛选</el-button>
						<el-button type="info" size="small" @click="resetList">重置</el-button>
					</el-form-item>
				</el-form>
				<!-- 发表文章的按钮 -->
				<el-button type="primary" size="small" class="btn-pub" @click="showPubDialog">发表文章</el-button>
			</div>
			<!-- 发表文章对话框start -->
			<el-dialog title="发表文章" :visible.sync="pubDialogVisible" fullscreen :before-close="handleClose"
				@closed="onDialogClosed">
				<!-- 发布文章的对话框 -->
				<el-form :model="pubForm" :rules="pubFormRules" ref="pubFormRef" label-width="100px">
					<el-form-item label="文章标题" prop="title">
						<el-input v-model="pubForm.title" placeholder="请输入标题"></el-input>
					</el-form-item>
					<el-form-item label="文章分类" prop="cate_id">
						<el-select v-model="pubForm.cate_id" placeholder="请选择分类" style="width: 100%;">
							<!-- 循环渲染分类的可选项 -->
							<el-option :label="item.cate_name" :value="item.id" v-for="item in cateList" :key="item.id">
							</el-option>
						</el-select>
					</el-form-item>
					<!-- 文章内容 -->
					<el-form-item label="文章内容" prop="content">
						<!-- 使用 v-model 进行双向数据绑定 -->
						<quill-editor v-model="pubForm.content"></quill-editor>
					</el-form-item>
					<!-- 文章封面 -->
					<el-form-item label="文章封面">
						<!-- 用来显示封面的图片 -->
						<img src="../../../assets/images/cover.jpg" alt="" class="cover-img" ref="imgRef" />
						<br />
						<!-- 文件选择框，默认被隐藏 -->
						<input type="file" style="display: none;" accept="image/*" ref="iptFile"
							@change="onloadCover" />
						<!-- 选择封面的按钮 -->
						<el-button type="text" @click="chooseImg">+ 选择封面</el-button>
					</el-form-item>
					<el-button style="margin-left: 100px;" type="primary" @click="pubArticle('已发布')">发布</el-button>
					<el-button type="info" @click="pubArticle('草稿')">存为草稿</el-button>
				</el-form>
			</el-dialog>
			<!-- 发表文章对话框end -->

			<!-- 文章表格区域 -->
			<el-table :data="artList" style="width: 100%;" border stripe>
				<el-table-column label="文章标题">
					<template v-slot="{ row }">
						<el-link type="primary" @click="showDetail(row.id)">{{ row.title }}</el-link>
					</template>
				</el-table-column>
				<el-table-column label="分类" prop="cate_name"></el-table-column>
				<el-table-column label="发表时间">
					<template v-slot="{ row }">
						{{ row.pub_date | dateFormat }}
					</template>
				</el-table-column>
				<el-table-column label="状态" prop="state"></el-table-column>
				<el-table-column label="操作">
					<template v-slot="{ row }">
						<el-button type="danger" size="mini" @click="remove(row.id)">删除</el-button>
					</template>
				</el-table-column>
			</el-table>

			<!-- 分页区域 -->
			<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
				:current-page="q.pagenum" :page-sizes="[2, 3, 5, 10]" :page-size="q.pagesize"
				layout="total, sizes, prev, pager, next, jumper" :total="total">
			</el-pagination>

		</el-card>
		<!-- 查看文章详情的对话框 -->
		<el-dialog title="文章预览" :visible.sync="detailVisible" width="80%">
			<h1 class="title">{{ artDetail.title }}</h1>

			<div class="info">
				<span>作者：{{ artDetail.nickname || artDetail.username }}</span>
				<span>发布时间：{{ artDetail.pub_date | dateFormat }}</span>
				<span>所属分类：{{ artDetail.cate_name }}</span>
				<span>状态：{{ artDetail.state }}</span>
			</div>

			<!-- 分割线 -->
			<el-divider></el-divider>

			<img :src="'http://big-event-vue-api-t.itheima.net' + artDetail.cover_img" alt="" />

			<div v-html="artDetail.content"></div>
		</el-dialog>
	</div>
</template>

<script>
	// 导入默认的封面图片
	import defaultImg from '@/assets/images/cover.jpg'
	export default {
		name: 'ArtList',
		data() {
			return {
				detailVisible: false, // 控制文章预览区的对话框的显示和隐藏
				// 文章的详情信息对象
				artDetail: {},
				// 文章的列表数据
				artList: [],
				// 总数据条数
				total: 0,
				// 文章分类
				cateList: [],
				// 查询参数对象
				q: {
					pagenum: 1,
					pagesize: 2,
					cate_id: '',
					state: ''
				},
				// 控制发表文章对话框的显示与隐藏
				pubDialogVisible: false,
				// 表单的数据对象
				pubForm: {
					title: '',
					cate_id: '',
					// 用户选择的封面图片（null 表示没有选择任何封面）
					cover_img: null,
					// 文章的发布状态，可选值有两个：草稿、已发布
					state: ''
				},
				// 表单的验证规则对象
				pubFormRules: {
					title: [{
							required: true,
							message: '请输入文章标题',
							trigger: 'blur'
						},
						{
							min: 1,
							max: 30,
							message: '文章标题的长度为1-30个字符',
							trigger: 'blur'
						}
					],
					cate_id: [{
						required: true,
						message: '请选择文章分类',
						trigger: 'change'
					}],
					content: [{
						required: true,
						message: "请输入文章内容",
						trigger: "blur"
					}, ]
				}
			}
		},
		created() {
			this.initCateList()
			// 请求文章的列表数据
			this.initArtList()
		},
		methods: {
			// 根据 id 删除文章
			async remove(id) {
				// 1. 询问用户是否要删除
				const confirmResult = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).catch(err => err)

				// 2. 取消了删除
				if (confirmResult === 'cancel') return

				// 执行删除的操作
				const {
					data: res
				} = await this.$http.delete('/my/article/info', {
					params: {
						id
					}

				})

				if (res.code !== 0) return this.$message.error('删除失败!')
				this.$message.success('删除成功!')
				// 如果在刷新数据之前,当前页的数据只有 1 条，
				// 而且，当前的页码值 > 1，
				// 则说明当前页已没有数据可显示，需要让页码值 -1
				if (this.artList.length === 1 && this.q.pagenum > 1) {
					this.q.pagenum--
				}
				// 刷新列表数据
				this.initArtList()
			},
			// 展示文章详情
			async showDetail(id) {
				// 请求详情数据
				const {
					data: res
				} = await this.$http.get('/my/article/info', {
					params: {
						id
					}
				})
				if (res.code !== 0) return this.$message.error('获取文章详情失败!')
				this.artDetail = res.data
				this.detailVisible = true
			},
			// 重置文章的列表数据
			resetList() {
				// 1. 重置查询参数对象
				this.q = {
					pagenum: 1,
					pagesize: 2,
					cate_id: '',
					state: ''
				}
				// 2. 重新发起请求
				this.initArtList()
			},
			// pageSize 发生了变化
			handleSizeChange(newSize) {
				// 为 pagesize 赋值
				this.q.pagesize = newSize
				// 默认展示第一页数据
				this.pagenum = 1
				// 重新发起请求
				this.initArtList()
			},
			// 页面跳转时触发
			handleCurrentChange(newPage) {
				// 设置q对象中pagenum页码数 
				this.q.pagenum = newPage;
				// 重新获取文章的数据
				this.initArtList();
			},
			// 获取文章列表数据
			async initArtList() {
				// 发送请求，获取数据
				const {
					data: res
				} = await this.$http.get("/my/article/list", {
					params: this.q,
				});
				// 发送请求失败，提示用户
				if (res.code !== 0) return this.$message.error('获取文章列表数据失败！')
				// 保存到data函数中
				this.total = res.total
				this.artList = res.data

			},
			// 发布文章或草稿
			pubArticle(state) {
				// 1. 设置发布状态
				this.pubForm.state = state
				// 2. 表单预校验
				this.$refs.pubFormRef.validate(valid => {
					if (!valid) return this.$message.error('请完善文章信息！')
					// 3. 判断是否提供了文章封面
					if (!this.pubForm.cover_img) return this.$message.error('请选择文章封面！')
					// 4. TODO：发布文章
					this.postArticle()
				})
			},
			// 发起请求，发布文章
			async postArticle() {
				// 1. 创建 FormData 对象
				const fd = new FormData()

				// 2. 向 FormData 中追加数据
				Object.keys(this.pubForm).forEach(key => {
					fd.append(key, this.pubForm[key])
				})

				// 3. 发起请求
				const {
					data: res
				} = await this.$http.post('/my/article/add', fd)
				if (res.code !== 0) return this.$message.error('发布文章失败！')
				this.$message.success('发布文章成功！')

				// 4. 关闭对话框
				this.pubDialogVisible = false
				// 5. TODO：刷新文章列表数据
				this.initArtList()
			},
			// 对话框完全关闭之后的处理函数
			onDialogClosed() {
				// 清空关键数据
				this.$refs.pubFormRef.resetFields()
				this.content = ''
				this.pubForm.cover_img = null
				this.pubForm.state = ''
				this.$refs.imgRef.setAttribute('src', defaultImg)
			},
			// 选择图片处理函数
			onloadCover(e) {
				// 获取用户选择的文件列表
				const files = e.target.files
				if (files.length === 0) {
					// 用户没有选择封面
					this.pubForm.cover_img = null
					// 设置默认图片的地址
					this.$refs.imgRef.setAttribute('src', defaultImage)
				} else {
					// 用户选择了封面
					this.pubForm.cover_img = files[0]
					const url = URL.createObjectURL(files[0])
					this.$refs.imgRef.setAttribute('src', url)
				}
			},
			// 选择图片模拟
			chooseImg() {
				this.$refs.iptFile.click()
			},
			// 展示发布文章的对话框
			showPubDialog() {
				this.pubDialogVisible = true
			},
			// 关闭事件的处理函数
			async handleClose(done) {
				// 询问用户是否确认关闭对话框
				const confirmResult = await this.$confirm('此操作将导致文章信息丢失, 是否继续?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).catch(err => err)

				// 取消了关闭
				if (confirmResult === 'cancel') return
				// 确认关闭
				done()
			},
			// 初始化文章分类的列表数据
			async initCateList() {
				const {
					data: res
				} = await this.$http.get('/my/cate/list')
				if (res.code === 0) {
					this.cateList = res.data
				}
			},

		}
	}
</script>

<style lang="less" scoped>
	// 富文本样式
	/deep/ .ql-editor {
		min-height: 300px;
	}

	.search-box {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;

		.btn-pub {
			margin-top: 5px;
		}
	}

	// 设置图片封面的宽高
	.cover-img {
		width: 400px;
		height: 280px;
		object-fit: cover;
	}

	.el-pagination {
		margin-top: 15px;
	}

	.title {
		font-size: 24px;
		text-align: center;
		font-weight: normal;
		color: #000;
		margin: 0 0 10px 0;
	}

	.info {
		font-size: 12px;

		span {
			margin-right: 20px;
		}
	}
</style>
